package top.codef.gsonsupport;

import java.util.HashMap;
import java.util.Map;

import javax.money.MonetaryAmount;

import org.javamoney.moneta.FastMoney;
import org.javamoney.moneta.Money;
import org.javamoney.moneta.RoundedMoney;

import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;

import top.codef.gsonsupport.adapters.FastMoneyAdapter;
import top.codef.gsonsupport.adapters.MonetaMoneyAdapter;
import top.codef.gsonsupport.adapters.MonetaryAmountAdapter;
import top.codef.gsonsupport.adapters.RoundedMoneyAdapter;
import top.codef.money.interfaces.MercuryMonetaryAmountFormat;

public class MoneyGsonAdapterFactory implements TypeAdapterFactory {

	private final MercuryMonetaryAmountFormat mercuryMonetaryAmountFormat;

	private final Map<Class<? extends MonetaryAmount>, TypeAdapter<?>> map = new HashMap<>();

	public MoneyGsonAdapterFactory(MercuryMonetaryAmountFormat mercuryMonetaryAmountFormat) {
		this.mercuryMonetaryAmountFormat = mercuryMonetaryAmountFormat;
		map.put(MonetaryAmount.class, new MonetaryAmountAdapter(mercuryMonetaryAmountFormat));
		map.put(FastMoney.class, new FastMoneyAdapter(mercuryMonetaryAmountFormat));
		map.put(RoundedMoney.class, new RoundedMoneyAdapter(mercuryMonetaryAmountFormat));
		map.put(Money.class, new MonetaMoneyAdapter(mercuryMonetaryAmountFormat));
	}

	public MercuryMonetaryAmountFormat getMercuryMonetaryAmountFormat() {
		return mercuryMonetaryAmountFormat;
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
		Class<? super T> clazz = type.getRawType();
		TypeAdapter<?> adapter = map.get(clazz);
		return (TypeAdapter<T>) adapter;
	}

}
